﻿using System;
using System.Collections.Generic;
using System.Text;
using JWFW.SFL;

namespace JWFW.Model.Register
{
    #if Server
    /// <summary>
    /// 注册模块－服务端
    /// </summary>
    public class RegisterServer
    {
        /// <summary>
        /// 注册模块－服务端
        /// </summary>
        public RegisterServer()
        {
            s_b64_2.CodeTable = @"STUVWXYZbacdefghi$klABCDEFGHIJKLMNOPQRmnopqrstu!wxyz0123456789+/";
            s_b64_2.Pad = "j";
        }
        /// <summary>
        /// Base64加密类1
        /// </summary>
        private static Encrypt.Base64 s_b64 = new BYFW.Encrypt.Base64();
        /// <summary>
        /// Base64加密类2
        /// </summary>
        private static Encrypt.Base64 s_b64_2 = new BYFW.Encrypt.Base64();

        #region 单机注册

        /// <summary>
        /// 获得单机版的注册码（RC）。
        /// 流程：
        /// 1.机器码（MC）先B64-1加密
        /// 2.过期时间（ET）按照ssmmhhddMMyy方式获取字符串
        /// 3.MC的第一位/3，得到ET的第一段长度，并安插在MC的这个位置
        /// 4.按照步骤3做4次
        /// 5.CRC第一个：取原前4位，做字符求和，映射到65-122，放在首位
        /// 6.CRC第二个：取原中4位，做字符求和，映射到65-122，放在次位
        /// 7.CRC第三个：取新前4位，做字符求和，映射到65-122，放在最后
        /// 8.CRC第四个：取新后4位，做字符求和，映射到65-122，放在最后
        /// 9.B64-2加密得到RC
        /// <param name="machineCode">客户电脑的机器码</param>
        /// <param name="expireTime">到期时间</param>
        /// <returns>用于客户指定机器注册的注册码</returns>
        protected static string GetPCRegisterCode(string machineCode, DateTime expireTime)
        {
            string mc = s_b64.Encode(machineCode);
            string et = expireTime.ToString("ddMMyy");
            string cj = CrossJoin(mc, et);
            string crc = AddCRC(cj);
            return s_b64_2.Encode(crc);
        }
        /// <summary>
        /// 获取交叉后的字符串
        /// </summary>
        /// <param name="mc"></param>
        /// <param name="et"></param>
        /// <returns></returns>
        protected static string CrossJoin(string mc, string et)
        {
            int div = 2;
            int times = 3;
            int length = 1;// char.ConvertToUtf32(mc, 0) % div;
            int posMC = 0;
            int posET = -1;
            string res = mc.Substring(0, 1);
            for (int i = 0; i < times; i++)
            {
                length = char.ConvertToUtf32(mc, posMC) % div + 1;
                res += et.Substring(posET + 1, length);
                res += mc.Substring(posMC + 1, length);//note: 当times和div都大时，length可能会越界
                posMC += length;
                posET += length;
            }
            if (posMC < mc.Length)
            {
                res += mc.Substring(posMC + 1);
            }
            if (posET < et.Length)
            {
                res += et.Substring(posET + 1);
            }
            return res;
        }
        /// <summary>
        /// 添加CRC字符
        /// </summary>
        /// <param name="rc"></param>
        /// <returns></returns>
        protected static string AddCRC(string rc)
        {
            int length = 4;
            string crc1 = CommonOP.GetMappedSum(rc, 0, length);
            string crc2 = CommonOP.GetMappedSum(rc, 4, length);
            rc = crc1 + crc2 + rc;
            string crc3 = CommonOP.GetMappedSum(rc, 0, length);
            rc = rc + crc3;
            string crc4 = CommonOP.GetMappedSum(rc, rc.Length - length, length);
            rc = rc + crc4;
            return rc;
        }

        #endregion

        #region 网络验证：所有异常返回值：【fail：信息不对】，【expire：过期】，【serverFail：服务端程序出错】，【isLastest：是最新版本】，【occupy：帐号被其他机器占用】

        /// <summary>
        /// 根据客户端提交的帐户信息，解析成帐户类
        /// </summary>
        /// <param name="clientInfo">客户端提交的帐户信息</param>
        /// <returns>帐户类</returns>
        protected static BRL.Account GetAccount(string clientInfo)
        {
            string[] infos = s_b64.Decode(clientInfo).Split(SFL.CommonOP.Spliter.ToCharArray());
            if (infos.Length != 6 && infos.Length != 7)
            {
                throw new BOL.BaseCustomException("fail");
            }
            BRL.Account act = new BYFW.Model.Register.BRL.Account();
            act.Name = infos[1].Trim();
            BRL.Tool tl = new BYFW.Model.Register.BRL.Tool();
            tl.GetProperties(infos[2].Trim());
            act.ToolID = tl.ID;
            act.SpecialInfo = infos[3].Trim();
            act.MachineCode = infos[4].Trim();
            act.RegisterCode = infos[5].Trim();
            if (infos.Length == 7)
            {
                act.Comment = infos[6].Trim();
            }
            if (tl.ID == 0 || act.Name == "" || act.MachineCode == "")
            {
                throw new BOL.BaseCustomException("fail");
            }
            return act;
        }
        /// <summary>
        /// 根据帐户信息，生成注册码
        /// </summary>
        /// <param name="account">帐户</param>
        /// <returns>生成的注册码</returns>
        protected static string GetRCNetRegister(BRL.Account account)
        {
            string origin = account.Name.ToLower() + account.SpecialInfo.ToLower() + account.Tool.Code.ToLower();
            return BYFW.Encrypt.MD5.GetMD5_32(s_b64_2.Encode(s_b64.Encode(origin)));
        }

        /// <summary>
        /// 验证帐户信息是否有效
        /// </summary>
        /// <param name="clientInfo">客户端提交的帐户信息</param>
        /// <returns>软件运行所需信息或错误信息</returns>
        public static string ValidateAccount(string clientInfo)
        {
            try
            {
                BRL.Account act = GetAccount(clientInfo);
                string mc = act.MachineCode;
                string rc = act.RegisterCode;
                if (act.ExistSpecialAccount())
                {
                    act.GetProperties(act.Name, act.ToolID, act.SpecialInfo);
                }
                else
                {
                    return s_b64.Encode("fail");
                }
                if (act.ExpireDate < DateTime.Now)
                {
                    return s_b64.Encode("expire");
                }
                if (act.RegisterCode != rc)
                {
                    return s_b64.Encode("fail");
                }
                if (!act.IsEnterprise && act.MachineCode != mc)
                {
                    act.MachineCode = mc;
                    act.Update();
                }
                if (act.IsEnterprise)
                {
                    if (act.MCRanger.IndexOf(mc + ";") == -1)
                    {
                        return s_b64.Encode("fail");
                    }
                }
                return s_b64.Encode(SFL.CommonOP.Spliter + s_b64.Encode(act.Name + SFL.CommonOP.Spliter + act.RegisterCode + SFL.CommonOP.Spliter + act.Tool.SpecialInfo));
            }
            catch (BOL.BaseCustomException ex)
            {
                return s_b64.Encode(ex.Message);
            }
            catch
            {
                return s_b64.Encode("serverFail");
            }           
        }
        /// <summary>
        /// 申请试用版，当帐户不存在时有效
        /// </summary>
        /// <param name="clientInfo">客户端提交的帐户信息</param>
        /// <returns>注册码或错误信息</returns>
        public static string TrivialAccount(string clientInfo)
        {
            try
            {
                BRL.Account act = GetAccount(clientInfo);
                if (act.ExistSpecialAccount())
                {
                    act.GetProperties(act.Name, act.ToolID, act.SpecialInfo);
                }
                else
                {
                    act.RegisterCode = GetRC(act);
                    act.ExpireDate = DateTime.Now.AddDays(act.Tool.TryDays);
                    act.Add();
                }
                return s_b64.Encode(SFL.CommonOP.Spliter + s_b64.Encode(act.RegisterCode));
            }
            catch (BOL.BaseCustomException ex)
            {
                return s_b64.Encode(ex.Message);
            }
            catch
            {
                return s_b64.Encode("serverFail");
            }

        }

        /// <summary>
        /// 获取信息，当机器码不一致时，失败
        /// </summary>
        /// <param name="clientInfo">客户端提交的帐户信息</param>
        /// <returns>软件运行所需信息或错误信息</returns>
        public static string GetInfo(string clientInfo)
        {
            try
            {
                BRL.Account act = GetAccount(clientInfo);
                string mc = act.MachineCode;
                string rc = act.RegisterCode;
                if (act.ExistSpecialAccount())
                {
                    act.GetProperties(act.Name, act.ToolID, act.SpecialInfo);
                }
                else
                {
                    return s_b64.Encode("fail");
                }
                if (act.ExpireDate < DateTime.Now)
                {
                    return s_b64.Encode("expire");
                }
                if (act.RegisterCode != rc)
                {
                    return s_b64.Encode("fail");
                }
                if (!act.IsEnterprise && act.MachineCode != mc)
                {
                    return s_b64.Encode("occupy");
                }
                if (act.IsEnterprise)
                {
                    if (act.MCRanger.IndexOf(mc + ";") == -1)
                    {
                        return s_b64.Encode("fail");
                    }
                }
                return s_b64.Encode(SFL.CommonOP.Spliter + s_b64.Encode(act.Name + SFL.CommonOP.Spliter + act.RegisterCode + SFL.CommonOP.Spliter + act.Tool.SpecialInfo));
            }
            catch (BOL.BaseCustomException ex)
            {
                return s_b64.Encode(ex.Message);
            }
            catch
            {
                return s_b64.Encode("serverFail");
            }
        }

        #endregion

        /// <summary>
        /// 获取新版本
        /// </summary>
        /// <param name="clientInfo">客户端提交的帐户信息</param>
        /// <returns>新版本链接或错误信息</returns>
        public static string GetNewVersionUrl(string clientInfo)
        {
            try
            {
                BRL.Account act = GetAccount(clientInfo);
                string mc = act.MachineCode;
                string rc = act.RegisterCode;
                string version = act.Comment;
                if (act.ExistSpecialAccount())
                {
                    act.GetProperties(act.Name, act.ToolID, act.SpecialInfo);
                }
                else
                {
                    return s_b64.Encode("fail");
                }
                if (act.ExpireDate < DateTime.Now)
                {
                    return s_b64.Encode("expire");
                }
                if (act.RegisterCode != rc)
                {
                    return s_b64.Encode("fail");
                }
                if (version == act.Tool.LastVersion)
                {
                    return s_b64.Encode("isLastest");
                }
                if (!act.Tool.ClientValidate)
                {
                    if (!act.IsEnterprise && act.MachineCode != mc)
                    {
                        return s_b64.Encode("occupy");
                    }
                    if (act.IsEnterprise)
                    {
                        if (act.MCRanger.IndexOf(mc + ";") == -1)
                        {
                            return s_b64.Encode("fail");
                        }
                    }
                }

                return s_b64.Encode(SFL.CommonOP.Spliter + s_b64.Encode(act.Tool.Url));
            }
            catch (BOL.BaseCustomException ex)
            {
                return s_b64.Encode(ex.Message);
            }
            catch
            {
                return s_b64.Encode("serverFail");
            }
        }
        /// <summary>
        /// 根据帐户信息，生成注册码
        /// </summary>
        /// <param name="account">帐户</param>
        /// <returns>生成的注册码</returns>
        public static string GetRC(BRL.Account account)
        {
            if (account.Tool.ClientValidate)
            {
                return GetPCRegisterCode(account.Name, account.ExpireDate);
            }
            else
            {
                return GetRCNetRegister(account);
            }
        }


        protected void Test()
        {
            BOL.BaseEntity.ConnStr = s_b64.Decode("c2VydmVyPTc1LjEyNy42OS4xNDE7dWlkPWJha3lhamc7cGFzc3d!cmQ9dmAxO2RhdGFiYXNlPW94cGd0ZXN0MQvv");
            string info = "xKxndDAwMsSscWxqxKxodHRwOi8!ZDEuZHVubXUuY29tL8SsUVZsVVFsWmJSaEJUV1ZbTMSsZjk5ZGFhYTkzM2FlZDg1MzdlMzllNjJmNTZmMzZmMWTErDEuMC4wLjAv";
            string res = RegisterServer.ValidateAccount(info);
            Console.WriteLine(res);
                return;
            ValidateReg vr = new ValidateReg();
            vr.Url = "http://localhost:3945/ValidateReg.asmx";
            string clientInfo = s_b64.Encode(SFL.CommonOP.Spliter + "gt002" + SFL.CommonOP.Spliter + "qlj" + SFL.CommonOP.Spliter + "http://new 5" + SFL.CommonOP.Spliter + "123" + SFL.CommonOP.Spliter + "41960b147b24987ae44b5c069d91c645");

            string ret = vr.TrivialAccount(clientInfo);
            ret = s_b64.Decode(ret.Substring(1));
            Console.WriteLine(ret);
        }
    }
#endif
}
